const childProcess = require('child_process')
const fs = require('fs');
const path = require('path');
const vscode = require('vscode');
const { logInfo, logError } = require('./logger');

const base64Encode = (string) => Buffer.from(string).toString('base64');

// RSA加密函数 - 使用node-rsa，模拟jsencrypt的行为
async function rsaEncrypt(string, publicKey) {
    try {
        const NodeRSA = require('node-rsa');
        const key = new NodeRSA();
        
        // 导入公钥
        key.importKey(publicKey, 'public');
        
        // 设置与jsencrypt相同的选项
        key.setOptions({
            encryptionScheme: 'pkcs1' // jsencrypt使用PKCS1填充
        });
        
        // 对内容进行加密，直接返回base64格式（模拟jsencrypt的行为）
        const encrypted = key.encrypt(string, 'base64');
        
        return encrypted;
    } catch (error) {
        logError('RSA加密失败:', error);
        throw new Error(`RSA加密失败: ${error.message}`);
    }
}

// 获取密码加密配置
async function getPasswordEncryptConfig(baseUrl) {
    try {
        const encryptUrl = `${baseUrl}/user/password/encrypt`;
        logInfo('获取密码加密配置:', encryptUrl);
        
        const response = await fetch(encryptUrl, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        });
        
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        
        const result = await response.json();
        logInfo('密码加密配置:', result);
        return result;
    } catch (error) {
        logError('获取密码加密配置失败:', error);
        // 如果获取加密配置失败，返回null，使用默认的base64加密
        return null;
    }
}

// 根据算法类型加密密码 - 模拟原来的encryptPWD函数
async function encryptPassword(password, encryptConfig) {
    if (!encryptConfig || !encryptConfig.currentAlgorithm) {
        // 没有加密配置，使用默认的base64编码
        logInfo('使用默认base64编码');
        return base64Encode(password);
    }
    
    const algorithm = encryptConfig.currentAlgorithm.toLowerCase();
    logInfo('使用加密算法:', algorithm);
    
    switch (algorithm) {
        case 'rsa': {
            if (!encryptConfig.publicKey) {
                throw new Error('RSA加密缺少公钥');
            }
            // 1. 先用RSA加密（返回base64格式）
            const rsaEncrypted = await rsaEncrypt(password, encryptConfig.publicKey);
            // 2. 再对RSA加密结果进行base64编码（模拟js-base64的行为）
            return base64Encode(rsaEncrypted);
        }
        
        case 'base64':
        default:
            return base64Encode(password);
    }
}

// 从.env文件读取端口配置
function getPortFromEnv(portKey, defaultPort) {
    const envPath = getProjectFile('.env')
    if (!fs.existsSync(envPath)) return defaultPort

    const envData = fs.readFileSync(envPath, 'utf8');
    const portLine = envData.split('\n').find(line => line.startsWith(`${portKey}=`))
    if (!portLine) return defaultPort

    const port = parseInt(portLine.split('=')[1])
    return isNaN(port) ? defaultPort : port
}

// 保存端口配置到.env文件
function savePortToEnv(portKey, port) {
    const envPath = getProjectFile('.env')
    
    let envData = '';
    if (fs.existsSync(envPath)) {
        envData = fs.readFileSync(envPath, 'utf8');
    }

    const lines = envData.split('\n');
    const portIndex = lines.findIndex(line => line.startsWith(`${portKey}=`));
    
    if (portIndex !== -1) {
        // 更新现有的端口
        lines[portIndex] = `${portKey}=${port}`;
    } else {
        // 添加新的端口配置
        lines.push(`${portKey}=${port}`);
    }

    // 确保文件以换行符结尾
    const newContent = lines.join('\n');
    fs.writeFileSync(envPath, newContent.endsWith('\n') ? newContent : newContent + '\n', 'utf8');
    
    console.log(`端口配置已保存到.env文件: ${portKey}=${port}`);
}

// 获取代理服务器端口
function getProxyServerPort() {
    try {
        // 先从.env文件读取配置的端口
        const envPort = getPortFromEnv('PROXY_SERVER_PORT', null);
        if (envPort) {
            logInfo(`从.env文件读取到代理服务器端口: ${envPort}`);
            return envPort;
        }

        // 尝试从代理服务器获取当前端口
        const { getProxyServer } = require('./proxyServer');
        const proxyServer = getProxyServer();
        return proxyServer.getPort();
    } catch (error) {
        logInfo('无法获取代理服务器端口，使用默认端口3838');
        return 3838;
    }
}

function getProjectFile(relativePath) {
    try {
        // 确保有工作区
        if (!vscode.workspace.workspaceFolders || !vscode.workspace.workspaceFolders.length) {
            return null
        }

        const workspacePath = vscode.workspace.workspaceFolders[0].uri.fsPath;
        const fullPath = path.join(workspacePath, relativePath);

        return fullPath;
    } catch (error) {
        vscode.window.showErrorMessage(`读取文件失败: ${error.message}`);
        return null;
    }
}

function getCurrentAccount() {
    const packageJsonPath = getProjectFile('package.json')
    if (!fs.existsSync(packageJsonPath)) return
    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
    if (packageJson.name !== 'guandata-web') return

    const envPath = getProjectFile('.env')
    if (!fs.existsSync(envPath)) {
        // 创建空的.env文件
        fs.writeFileSync(envPath, '', 'utf8');
    }

    const envData = fs.readFileSync(envPath, 'utf8');
    const env = envData.split('\n').find(line => line.startsWith('ENVIRONMENT='))
    if (!env) return

    const environment = JSON.parse(env.split('=')[1])
    return environment
}

function getCurrentToken() {
    const envPath = getProjectFile('.env')
    if (!fs.existsSync(envPath)) return null

    const envData = fs.readFileSync(envPath, 'utf8');
    const tokenLine = envData.split('\n').find(line => line.startsWith('AUTH_TOKEN='))
    if (!tokenLine) return null

    return tokenLine.split('=')[1]
}

function saveToken(token) {
    const envPath = getProjectFile('.env')
    
    let envData = '';
    if (fs.existsSync(envPath)) {
        envData = fs.readFileSync(envPath, 'utf8');
    }

    const lines = envData.split('\n');
    const tokenIndex = lines.findIndex(line => line.startsWith('AUTH_TOKEN='));
    
    if (tokenIndex !== -1) {
        // 更新现有的token
        lines[tokenIndex] = `AUTH_TOKEN=${token}`;
    } else {
        // 添加新的token
        lines.push(`AUTH_TOKEN=${token}`);
    }

    // 确保文件以换行符结尾
    const newContent = lines.join('\n');
    fs.writeFileSync(envPath, newContent.endsWith('\n') ? newContent : newContent + '\n', 'utf8');
    
    logInfo('Token已保存到.env文件');
}

async function refreshDevLogin(config, apiMode = false) {
    const { domain, loginId, password, host, port, browser, vendor, emailLogin } = config

    const configPath = getProjectFile('packages/server/conf/configuration.json')
    if (!fs.existsSync(configPath)) return

    // 检查是否是代理模式（没有host或port）
    const useProxy = !host || !port;
    let targetHost = host;
    let targetPort = port;
    
    if (useProxy) {
        // 代理模式：使用本地127.0.0.1和代理服务器端口
        targetHost = '127.0.0.1';
        targetPort = getProxyServerPort();
        logInfo('使用代理模式，配置host为127.0.0.1，port为' + targetPort);
    }

    const envPath = getProjectFile('.env')
    const environment = JSON.stringify({ 
        ...config,
        useProxy: useProxy,
        originalHost: host,
        originalPort: port
    })
    
    if (!fs.existsSync(envPath)) {
        fs.writeFileSync(envPath, `ENVIRONMENT=${environment}\n`, 'utf8');
    } else {
        const envData = fs.readFileSync(envPath, 'utf8');
        const env = envData.split('\n').find(line => line.startsWith('ENVIRONMENT='))
        if (!env) {
            // 如果文件存在，读取现有内容并追加
            let existingContent = '';
            if (fs.existsSync(envPath)) {
                existingContent = fs.readFileSync(envPath, 'utf8');
                if (!existingContent.endsWith('\n')) {
                    existingContent += '\n';
                }
            }
            fs.writeFileSync(envPath, `${existingContent}ENVIRONMENT=${environment}\n`, 'utf8');
        } else {
            const newEnvData = envData.replace(/ENVIRONMENT=.*/, `ENVIRONMENT=${environment}`);
            fs.writeFileSync(envPath, newEnvData, 'utf8');
        }
    }

    const login = async () => {
        const startTime = new Date();
        
        // 根据是否使用代理模式选择不同的登录URL和基础URL
        let loginUrl, baseUrl;
        if (useProxy) {
            // 代理模式：使用账号配置中的url进行登录
            if (!config.url) {
                const errorMsg = '代理模式需要配置账号的url字段';
                if (apiMode) {
                    throw new Error(errorMsg);
                } else {
                    vscode.window.showErrorMessage(errorMsg);
                    return;
                }
            }
            baseUrl = `${config.url}/api`;
            loginUrl = `${config.url}/api/user/sign-in`;
        } else {
            // 直连模式：直接连接目标服务器
            baseUrl = `http://${targetHost}:${targetPort}`;
            loginUrl = `http://${targetHost}:${targetPort}/user/sign-in`;
        }
        
        // 获取密码加密配置
        let encryptedPassword;
        try {
            const encryptConfig = await getPasswordEncryptConfig(baseUrl);
            encryptedPassword = await encryptPassword(password, encryptConfig);
        } catch (error) {
            logError('密码加密失败:', error);
            if (apiMode) {
                throw new Error(`密码加密失败: ${error.message}`);
            } else {
                vscode.window.showErrorMessage(`密码加密失败: ${error.message}`);
                return;
            }
        }
        
        const res = await fetch(loginUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                domain,
                [vendor === 'ldap' || emailLogin ? 'email' : 'loginId']: loginId,
                password: encryptedPassword,
                vendor,
            })
        })
        .then(res => res.json())
        .catch(e => {
            logError('登录请求失败:', e);
            vscode.window.showErrorMessage(`登录请求失败: ${e.message}`);
            return null;
        })
        
        console.log('登录响应:', res)
        const endTime = new Date();
        
        // 使用vscode API显示成功消息
        let token = null
        if (useProxy) {
            token = res && res.uIdToken ? res.uIdToken : null
        } else {
            token = res && res.response && res.response.token
        }
        
        if (token) {
            // 保存token到.env文件
            saveToken(token);
        } else {
            if (apiMode) {
                throw new Error('登录失败，未获取到token');
            } else {
                vscode.window.showErrorMessage('登录失败，未获取到token');
                return;
            }
        }

        // API模式下直接返回token，不打开浏览器
        if (apiMode) {
            return { 
                success: true, 
                token: token,
                message: '登录成功',
                loginTime: (endTime - startTime) + 'ms'
            };
        }

        const frontendUrl = `http://localhost:${configData.PORT + 1}?loginToken=${token}`;
        
        const command = 'open';
        const cliArguments = ['-a', browser || 'Google Chrome', frontendUrl];
        
        // 使用 execFile 替代 spawn，因为它更适合执行单个命令
        childProcess.execFile(command, cliArguments, (error) => {
            if (error) {
                vscode.window.showErrorMessage(`打开浏览器失败: ${error.message}`);
            }
        });
    }

    const configData = JSON.parse(fs.readFileSync(configPath, 'utf8'));
    
    // 检查是否需要更新配置
    const needUpdate = configData.BACKEND.PORT !== targetPort || configData.BACKEND.HOST !== targetHost;
    
    if (needUpdate) {
        configData.BACKEND.PORT = targetPort;
        configData.BACKEND.HOST = targetHost;
        fs.writeFileSync(configPath, JSON.stringify(configData, null, 2), 'utf8');
        
        if (apiMode) {
            // API模式下需要等待登录完成并返回结果
            return new Promise((resolve, reject) => {
                setTimeout(async () => {
                    try {
                        const result = await login();
                        resolve(result);
                    } catch (error) {
                        reject(error);
                    }
                }, 1000);
            });
        } else {
            setTimeout(() => {
                login();
            }, 1000);
        }
    } else {
        return await login();
    }
}
module.exports = { refreshDevLogin, getCurrentAccount, getCurrentToken, saveToken, getPortFromEnv, savePortToEnv }